<?php
class Slog_Db_Select
{
	protected $_tables = array();
	protected $_fields = array();
	
	protected $_join = array();
	protected $_where = array();
	protected $_limit = null;
	protected $_offset = null;
	protected $_order = array();
	protected $_group = array();
	
	protected $___table_aliases = array('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', );
	
	public function __toString()
	{
		return Slog_Db_Table::getDriver()->selectToSQL( $this );
	}
	
	public function join($table, $where, $fields)
	{
		return $this->_join($table, $where, $fields, Slog_Db_Select_Join::TYPE_INNER);
	}

	public function from($table, $fields)
	{
		return $this->_join($table, null, $fields, Slog_Db_Select_Join::TYPE_FROM);
	}

	public function joinLeft($table, $where, $fields)
	{
		return $this->_join($table, $where, $fields, Slog_Db_Select_Join::TYPE_LEFT);
	}
	
	public function escape($text)
	{
		return Slog_Db_Table::getDriver()->escape($text);
	}
	
	public function where($where)
	{
		$args = func_get_args();
		$where = array_shift($args);
		
		$last_q = null;
		while (($last_q = strpos($where, '?', $last_q)) !== false) {
			if ($where[$last_q-1] != '\\') {
				$where = substr($where, 0, $last_q) . '"' . $this->escape(array_shift($args)) . '"' . substr($where, $last_q+1);
			}
			$last_q++;
		}
		
		$this->_where[] = $where;
		
		return $this;
	}
	
	public function limit($limit, $offset = null)
	{
		$this->_limit = $limit;
		if ($offset !== null) $this->offset($offset);
		return $this;
	}
	public function offset($offset)
	{
		$this->_offset = $offset;
		return $this;
	}
	
	public function order($order)
	{
		if (is_string($order)) {
			$this->_order[] = $order;
		} else if (is_array($order)) {
			$this->_order = array_merge($this->_order, $order);
		} else {
			return null;
		}
		return $this;
	}
	
	public function group($field)
	{
		if (is_string($field)) {
			$this->_group[] = $field;
		} else if (is_array($field)) {
			$this->_group = array_merge($this->_group, $field);
		} else {
			return null;
		}
		return $this;
	}
	
	public function getJoins()
	{
		return $this->_join;
	}
	public function getFields()
	{
		return $this->_fields;
	}
	public function getTables()
	{
		return $this->_tables;
	}
	public function getWheres()
	{
		return $this->_where;
	}
	public function getLimit()
	{
		return $this->_limit;
	}
	public function getOffset()
	{
		return $this->_offset;
	}
	

	protected function _join($table, $where, $fields, $type)
	{
		// Tabla
		$table = $this->addTable($table);
		
		// Campos
		$fields = $this->addFields($table, $fields);

		$this->_join[] = new Slog_Db_Select_Join($table, $where, $fields, $type);
		
		return $this;
	}
	
	protected function addFields($table, $fields)
	{
		$F = array();
		
		if (!is_array($fields)) {
			$fields = array($fields);
		}
		
		foreach ($fields as $alias => $value) {
			if (is_numeric($alias)) $alias = $value;
			$this->_fields[$alias] = $value;
			$F[$alias] = $value;
		}
		
		return $F;
	}
	
	protected function addTable($table)
	{
		if (is_array($table)) {
			$table_alias = array_shift(array_keys($table));
			$table_name = array_shift($table);
		} else {
			$table_alias = $this->createTemporalTableAlias($table);
			$table_name = $table;
		}
		
		if ($table_name instanceof Slog_Db_Table) {
			$table_name = $table_name->getName();
		}
		
		$this->_tables[$table_name] = $table_alias;
		
		return $table_name;
	}
	
	protected function createTemporalTableAlias($tablename)
	{
		return array_shift($this->___table_aliases);
	}
	
}


class Slog_Db_Select_Join
{
	const TYPE_FROM		= 'from';
	const TYPE_INNER	= 'inner';
	const TYPE_LEFT		= 'left';

	public $table;
	public $where;
	public $fields;
	public $type;
	
	public function __construct($table, $where, $fields, $type)
	{
		$this->table = $table;
		$this->where = $where;
		$this->fields = $fields;
		$this->type = $type;
	}
}